package Core::List;
use strict;
use warnings;
use vars qw{ @ISA @EXPORT };
use Exporter;
use Core::ListIterator;

@ISA = qw( Exporter );
@EXPORT = qw (
   List
);





sub List
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
    my $rhMeta = Core::List->new( @_ );
    return $rhMeta;
}


sub new
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my( $rhClass ) = shift;               # Object    
    my( $rhSelf ) = {};
    bless( $rhSelf, $rhClass);
    
	my( $raList )    =   shift; 
    if( $raList and @{ $raList } ){
		$rhSelf->setList( $raList );
	}
	$rhSelf->selected();
    return $rhSelf;
}	

sub init
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{ 
	my( $rhSelf ) = shift;
	$rhSelf->{ LIST } = [ ];
}

sub setList
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my( $rhSelf ) = shift; 	
	# The list that contain the meta object
	my $raList = shift;
	return 0 if not defined $raList;
	
	$rhSelf->{ LIST } = $raList;
}

sub getList
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my( $rhSelf ) = shift; 	
	return $rhSelf->{ LIST };
}

sub add
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my ( $rhSelf ) = shift; 
		
	return 0 if not @_ or not defined $_[0];	
	
	push @{ $rhSelf->{ LIST } }, @_;
	return 1;
}

sub pop
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my ( $rhSelf ) = shift; 
	pop @{ $rhSelf->{ LIST } } if $rhSelf->{ LIST };
}

sub del
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{ 
	my ( $rhSelf ) = shift;
	my ( $sIndex  ) = shift;
	return 0 if not defined $sIndex or
				$sIndex >= $rhSelf->size();
				
	splice( @{ $rhSelf->{ LIST } }, $sIndex, 1 );
	return 1;
}	

sub set
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my ( $rhSelf ) = shift; 
	my ( $sIndex, $sValue ) = @_;
	
	$rhSelf->{ LIST }[ $sIndex ] = $sValue;
	return 1;
}

sub get
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my ( $rhSelf ) = shift; 
	my ( $sIndex ) = shift;
	return $rhSelf->{ LIST }[ $sIndex ];
}

sub first
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{ 
	my( $rhSelf ) = shift;
	return $rhSelf->{ LIST } ? $rhSelf->{ LIST }[ 0 ] : undef ;
}


sub last
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{ 
	my( $rhSelf ) = shift;
	return $rhSelf->{ LIST } ? $rhSelf->{ LIST }[ -1 ] : undef ;
}




sub size
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my( $rhSelf ) = shift;
	
	return 0 if not $rhSelf->{ LIST };
	return $#{ $rhSelf->{ LIST } } + 1;
}


sub isEmpty
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my( $rhSelf ) = shift;
	return 1 if not defined $rhSelf->{ LIST };
	return $#{ $rhSelf->{ LIST } } >= 0 ? 0 : 1;  
}

sub compare
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my( $rhSelf ) = shift;
	my ( $raValues ) = shift;
	
	return 0 if not $raValues or
				not @{ $raValues };
	
	return 0 if $#{ $raValues }	+ 1 != $rhSelf->size();
	
	foreach ( 0 .. $#{ $raValues } ){
		if( $rhSelf->get( $_ ) != $raValues->[ $_ ]  ){
			return 0;
		}
	}	
	
	return 1;
}

sub equals
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my( $rhSelf ) = shift;
	my( $rhList ) = shift;

	return 0 if not $rhList;
	return $rhSelf->compare( $rhList->getList() );	
}	

sub iterator
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my ( $rhSelf ) = shift;
	my ( $sID ) = $_[ 0 ] || 0;	
	
	my $rcFunc = sub {
		return $rhSelf->__getEndFlag() if $sID >= $rhSelf->size();
		return $rhSelf->{ LIST }[ $sID++ ];
	};
	
	return ListIterator( $rcFunc );
}

sub __getEndFlag
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my ( $rhSelf ) = shift;
	return "'__END__'";	
}	

sub begin
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my ( $rhSelf ) = shift;
	my ( $sBegin ) = 0;
	return $sBegin;	
}	

sub end
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my ( $rhSelf ) = shift;
	my ( $sEnd ) = -1;
	if( $rhSelf->size() ){
		$sEnd = $rhSelf->size() - 1;
	}	
	return $sEnd;
}	

sub range
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my ( $rhSelf ) = shift;
	return ( $rhSelf->begin() , $rhSelf->end() );	
}	


sub selected
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my( $rhSelf ) = shift;      
	$rhSelf->{ SELECT } = 1;
}

sub unselected
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my( $rhSelf ) = shift;      
	$rhSelf->{ SELECT } = 0;
}

sub isSelected
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my( $rhSelf ) = shift;    	
	$rhSelf->{ SELECT }  ? 1 : 0;
}
 
sub clone
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my( $rhSelf ) = shift;
	
	require Storable; 
    return  Storable::dclone( $rhSelf ); 
} 

sub toList
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my( $rhSelf ) = shift;
	return $rhSelf->{ LIST } ? @{ $rhSelf->{ LIST } } : ();
}	

sub toString
#*****************************************************************************
# PURPOSE:
# USAGE: 
# PASSED ARGS:
# RETURN ARGS:
# $sError - Fail Error Message
#*****************************************************************************
{
	my( $rhSelf ) = shift;
	my $sValue = "Element ( " . $rhSelf->size()  . " )\n";
	$sValue .= "[ ". join( ", ", $rhSelf->toList() ) . " ]\n";
	return $sValue;
}

